/*  
内置类型
1. 忽略对象中的指定属性, 如三个属性中忽略一个
-- Omit<Person, 'company' | 'age'> 将指定属性从对象中忽略掉，可以是多个
扩展类型，使用第三方库 mapped-types
1. 求两个对象的差集
-- Diff<A,B>  从 A 中找出 B 没有的属性
2. 求两个对象的交集
-- interSection<A,B>  中出 A，B 都有的属性
3. 覆盖，如果存在某属性，就用新的覆盖旧的
-- overWrite<A,B>  A 有 B 没有的就保留, A 有 B 也有的就取 B 的, A 没有 B 有的就丢弃；最终合并
4. 合并
-- merge<A,B> 类似于 Object.assign ,保留 B 的，忽略 A 有 B 也有的
5.显示对象属性类型
-- Compute<A> 如果A 是个交叉类型或者别的一眼不能显示清楚的类型，鼠标放上去可以立即显示A中的属性



*/

// Record 干什么用的
//---------------实现一个 map--------------
type Fn<K, T, U> = (item: K, key: T) => U
function map<K, U, T extends keyof any>(obj: Record<T, K>, cb: Fn<K, T, U>): Record<T, U> {
    let result = {} as Record<T, U>
    for (let key in obj) {
        result[key] = cb(obj[key], key)
    }
    return result
}

let r = map({ name: 'zs', age: 12 }, (item, key) => {
    return '23'
})
//----------------------------------------


interface Person1 {
    name: 'zs',
    age: 12,
    company: 'dj'
}
interface Person2 {
    name: 'LS',
    age: 23,
    aa: '2323'
}
//----------------Omit忽略指定属性---------
/* 
原理
1. 先将指定属性排除, 两个参数，第二个有约束，
2. 将排除后的属性再选取出来
 */
// type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>
type Omit<T, K extends any> = { [P in Exclude<keyof T, K>]: T[P]; }
type p = Omit<Person, 'company' | 'age'> //  忽略指定属性

//----------------------------------------


let p1 = {
    name: 'zs',
    age: 1,
    address: '中国'
}

let p2 = {
    address: '地球',
}

// ---------------求差集----------------
// 将不要的忽略掉
type Diff<T extends object, K extends object> = Omit<T, keyof K>  // 从T中将K忽略
type MyDiff = Diff<typeof p1, typeof p2>  // typeof 类型反推，获取对象的类型
// ------------------------------------
// ---------------求交集---------------
// 先用 Extract 从T中将共同部分抽出来，再 用 Pick 到指定对象中去取，就得到交集
type interSection<T extends object, K extends object> = Pick<T, Extract<keyof T, keyof K>>
type myinter = interSection<typeof p1, typeof p2>
// ------------------------------------

//-------------覆盖-------------------
// A 与 B, B 中多余属性丢弃, 与A 相同的属性,取B中的值,最后合并
type overWrite<T extends object, K extends object> = Pick<T, keyof Diff<T, K>> & Omit<K, keyof Diff<K, T>>
type myWrite = overWrite<Person1, Person2>

/* 
// 分三步走：
-- 1. 从 A 中取出两者不同作为保留，
-- 2，从 B 中取出两者不同作为丢弃, B 的其他属性保留，
-- 3. A B 取并集，即两者属性合并
 */
type xy = Pick<Person1, keyof Diff<Person1, Person2>> // 1
type xx = Omit<Person2, keyof Diff<Person2, Person1>> // 2
type myyWrite = xy & xx // 3

let xxxx: myyWrite = {
    name: 'LS',
    age: 23,
    company: 'dj'
}
let ppp: myWrite = {
    name: 'LS',
    age: 23,
    company: 'dj'
}
console.log('----', ppp)
//-----------------------------------


//---------------merg合并------------
let t1 = { name: 'zs', a: 23 }
let t2 = { age: 'zs', a: 'string' }
type t1 = typeof t1
type t2 = typeof t2

// 保留 K 的，忽略T有K也有的
type Merge<T, K> = K & Omit<T, keyof K>
type t3 = Merge<t1, t2>
let t: t3 = {
    a: 'ddd',
    age: 'rer',
    name: 'zs'
}
//-----------------------------------

//-------------Compute 显示对象属性-----
type Compute<T> = { [K in keyof T]: T[K] }
type tt = Compute<Merge<t1, t2>> //鼠标放上去可以立即显示 tt 的属性
//-----------------------------------

export { }